package dsk.demo.product.controller.product;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import dsk.demo.common.utils.PageUtils;
import dsk.demo.common.utils.R;
import dsk.demo.product.dto.ProductQueryDto;
import dsk.demo.product.dto.ProductSaveDto;
import dsk.demo.product.entity.ProductEntity;
import dsk.demo.product.service.ProductCarService;
import dsk.demo.product.service.ProductRefService;
import dsk.demo.product.service.ProductService;
import dsk.demo.product.service.SearchService;
import dsk.demo.product.util.StrUtil;
import dsk.demo.product.vo.ProductVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;


/**
 * @author daishikun
 * @email 940798525@qq.com
 * @date 2022-09-17 09:09:41
 */
@RestController
@Slf4j
@RequestMapping("product/product")
public class ProductController {
    @Autowired
    private ProductService productService;
    @Autowired
    private ProductCarService productCarService;
    @Autowired
    private ProductRefService productRefService;

    @Resource(name = "MyExecutor")
    private ThreadPoolTaskExecutor myExecutor;

    /**
     * 后端管理   查询产品列表
     */
    @RequestMapping("/list")
    @RequiresPermissions("product:product:list")
    public R list(@RequestBody ProductQueryDto dto) {
        PageUtils pageUtils = productService.queryHoutaiPage(dto);
        pageUtils.getList().stream().forEach(item -> {
            ProductVo vo = (ProductVo) item;
            if (vo.getOemList().size() > 5) {
                vo.setOemList(vo.getOemList().subList(0, 5));
            }
        });
        return R.ok().put("page", pageUtils);
    }

    /**
     * 后端管理   查询产品列表
     */
    @RequestMapping("/randomList")
    @RequiresPermissions("product:product:list")
    public R randomList(@RequestBody ProductQueryDto dto) {
        if (dto.getLimit() == null || dto.getLimit() < 0) {
            return R.error("limit 不可为空");
        }
        List<ProductVo> productVos = productService.queryRandomList(dto);
        return R.ok().put("page", productVos);
    }

    /**
     * 信息
     */
    @RequestMapping("/info/{id}")
    @RequiresPermissions("product:product:info")
    public R info(@PathVariable("id") Long id) {
        ProductVo product = productService.getDetailById(id);
        return R.ok().put("product", product);
    }

    /**
     * 保存
     */
    @RequestMapping("/save")
    @RequiresPermissions("product:product:save")
    @Transactional
    public R save(@RequestBody ProductSaveDto product) {
        try {
            product.setProductNo(product.getProductNo().trim());
            ProductEntity byId = productService.getById(product.getId());
            if (byId != null && !byId.getProductNo().equals(product.getProductNo())) {
                //同步修改  车型和  oem号码
                productCarService.updateCarProductNo(byId.getProductNo(), product.getProductNo());
                productRefService.updateRefProductNo(byId.getProductNo(), product.getProductNo());
            }
            productService.saveOrUpdateProduct(product);
        } catch (Exception e) {
            return R.error(501, "OEM号码重复");
        }
        return R.ok();
    }

    /**
     * excel批量上传
     */
    @RequestMapping("/saveList/{catalogId}")
    @RequiresPermissions("product:product:save")
    public R saveList(MultipartFile file, @PathVariable Long catalogId) {
        try {
            List<ProductEntity> productEntities = productService.excel2ProductEntityList(file);
            for (ProductEntity productEntity : productEntities) {
                productEntity.setCatalogId(catalogId);
                productEntity.setProductNo(productEntity.getProductNo().trim());
            }
            //先查询所有产品编号
            List<String> collect = productEntities.stream().map(item -> {
                return item.getProductNo();
            }).collect(Collectors.toList());
            List<ProductEntity> existList = productService.queryByProductNos(collect);
            //假如存在重复项，去除重复项
            List<String> existStringList = new ArrayList<>();
            if (existList != null && existList.size() > 0) {
                existStringList = existList.stream().map(item -> {
                    return item.getProductNo();
                }).collect(Collectors.toList());

                List<String> finalExistStringList = existStringList;
                productEntities = productEntities.stream().filter(item -> {
                    return finalExistStringList.indexOf(item.getProductNo()) < 0;
                }).collect(Collectors.toList());
            }
            //去除上传目录的重复项
            List<ProductEntity> finalList = new ArrayList<>();
            Set<String> nameSet = new HashSet<>();
            List<String> finalExistStringList1 = existStringList;
            productEntities.stream().forEach(item -> {
                if (!nameSet.contains(item.getProductNo())) {
                    finalList.add(item);
                    nameSet.add(item.getProductNo());
                } else {
                    finalExistStringList1.add(item.getProductNo());
                }
            });
            productService.saveOrUpdateBatch(finalList);
            return R.ok(existStringList.size() == 0 ?
                    "插入成功" : "以下几项数据本厂编号重复:" + finalExistStringList1.toString());
        } catch (Exception e) {
            return R.error(501, "上传失败");
        }
    }

    /**
     * excel批量价格修改
     */
    @RequestMapping("/updateList")
    @RequiresPermissions("product:product:save")
    public R updateList(MultipartFile file) {
        try {
            List<ProductEntity> productEntities = productService.excel2ProductEntityList(file);
            productService.updateList(productEntities);
            return R.ok("修改成功");
        } catch (Exception e) {
            return R.error(501, "上传失败");
        }
    }

    /**
     * 批量上传  所需的模板下载
     */
    @RequestMapping("/downloadTemp")
    @RequiresPermissions("product:product:save")
    public void downloadTemp(HttpServletResponse response) throws IOException {
        // 通过工具类创建writer，默认创建xls格式
        ExcelWriter writer = ExcelUtil.getWriter();
        //配置别名
        LinkedHashMap<String, String> map = new LinkedHashMap<>();
        map.put("productNo", "本厂编号");
        map.put("image", "图片地址");
        map.put("price", "价格");
        map.put("price1", "价格1");
        map.put("attributes", "属性");
        map.put("application", "车型");
        map.put("image1", "图片1");
        map.put("image2", "图片2");
        map.put("image3", "图片3");
        map.put("image4", "图片4");
        map.put("image5", "图片5");
        writer.setHeaderAlias(map);
        //只写入配置了别名的属性
        writer.setOnlyAlias(true);

        ProductEntity productEntity = new ProductEntity();
        List<ProductEntity> rows = new ArrayList<>();
        rows.add(productEntity);
        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(rows, true);
        //out为OutputStream，需要写出到的目标流

        //response为HttpServletResponse对象
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
        response.setHeader("Content-Disposition", "attachment;filename=temp.xls");
        ServletOutputStream out = response.getOutputStream();

        writer.flush(out, true);
        // 关闭writer，释放内存
        writer.close();
        //此处记得关闭输出Servlet流
        IoUtil.close(out);
    }

    /**
     * 修改
     */
    @RequestMapping("/update")
    @RequiresPermissions("product:product:update")
    public R update(@RequestBody ProductSaveDto product) {
        product.setProductNo(product.getProductNo().trim());
        ProductEntity byId = productService.getById(product.getId());
        if (byId != null && !byId.getProductNo().equals(product.getProductNo())) {
            //同步修改  车型和  oem号码
            productCarService.updateCarProductNo(byId.getProductNo(), product.getProductNo());
            productRefService.updateRefProductNo(byId.getProductNo(), product.getProductNo());
        }
        productService.saveOrUpdateProduct(product);
        return R.ok();
    }

    /**
     * 删除
     */
    @RequestMapping("/delete")
    @RequiresPermissions("product:product:delete")
    public R delete(@RequestBody Long[] ids) {
        productService.removeByIds(Arrays.asList(ids));
        return R.ok();
    }

    /**
     * 保存图片
     */
    @RequestMapping("/image/{productId}/{imageType}")
    public R saveImage(MultipartFile file, @PathVariable Long productId, @PathVariable Integer imageType, HttpServletRequest req) {
        String type = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
        String filename = UUID.randomUUID().toString() + type;
        Date date = new Date();
        int year = DateUtil.year(date);
        int month = DateUtil.month(date);

        //linux 系统中的  文件保存地址
        File fDir = new File(File.separator); //File.separator表示根目录，比如现在就表示在D盘下。
        String baseFileDir = "mydata" + File.separator + "nginx" + File.separator + "html" + File.separator + "images";
        String yearFileDir = baseFileDir + File.separator + year;
        String monthFileDir = yearFileDir + File.separator + month;
        File yearFile = new File(fDir, yearFileDir);
        if (!yearFile.exists()) {
            yearFile.mkdir();
        }
        File monthFile = new File(fDir, monthFileDir);
        if (!monthFile.exists()) {
            monthFile.mkdir();
        }

        File imageFile = new File(fDir, monthFileDir + File.separator + filename);
        //windows 系统种的 文件保存地址(测试用)
//        File fDir=new File("F:\\uploadFile\\");
//        File file1 = new File(fDir,filename);

        String filePath = "";
        try {
            file.transferTo(imageFile);
            filePath = req.getScheme() + "://" + req.getServerName()
                    + (req.getServerPort() == 80 ? "" : (":" + req.getServerPort()))
                     + "/images/" + year + "/" + month + "/" + filename;
            productService.saveImage(productId, filePath, imageType);

        } catch (IOException exception) {
            log.error("文件上传异常[{}]", exception);
            return R.error(500, "上传文件异常");
        }
        return R.ok().put("image", filePath);
    }

    @Autowired
    SearchService searchService;

    @PostMapping("/quote")
    public R quote(@RequestBody String[] oemList) {
        try {
            List<ProductVo> list = new ArrayList<>();
            List<ProductVo> productVos = Collections.synchronizedList(list);
            CountDownLatch latch = new CountDownLatch(oemList.length);
            List<String> strings = Arrays.asList(oemList);
            Map<String, List<ProductVo>> stringListMap = searchService.searchFoundStringList(strings);
            for (String s : oemList) {
                myExecutor.execute(()-> {
                    List<ProductVo> search = stringListMap.get(s);
                    Integer index1 = findIndex(oemList, s);
                    if (search == null || search.size() == 0) {
                        ProductVo productVo = new ProductVo();
                        productVo.setCustomerNo(s);
                        productVo.setOrder(index1);
                        productVos.add(productVo);
                    } else {
                        search.stream().forEach(item -> {
                            item.setCustomerNo(s);
                            item.setOrder(index1);
                        });
                        productVos.addAll(search);
                    }
                    latch.countDown();
                });
            }
            latch.await();
            productVos.stream().forEach(item -> {
                if (item.getOemList() != null && item.getOemList().size()>0) {
                    item.dealReturnOemList();
                }
                if (item.getCarList() != null && item.getCarList().size()>0) {
                    item.setCarList(item.getCarList().subList(0,item.getCarList().size()>5? 5 : item.getCarList().size()));
                }
            });
            productVos.sort((o1, o2) -> o1.getOrder() - o2.getOrder());
            return R.ok().put("list", productVos);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getLocalizedMessage());
            return R.error().put("500", "查询失败");
        }
    }

    private Integer findIndex(String[] oemList, String s) {
        for (int i = 0; i < oemList.length; i++) {
            if (oemList[i] != null && oemList[i].equals(s)) {
                return i;
            }
        }
        return 0;
    }

    @PostMapping("/quoteExport")
    public void quote(@RequestBody ProductVo[] productVo, HttpServletResponse response) {
        try {
            searchService.quoteExport(productVo, response);
        } catch (Exception e) {
            System.out.println(e.getLocalizedMessage());
        }
    }
}
